package com.ufgov.smartclient.component.table;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Vector;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 * 功能描述：可分组表头
 * 创建时间：2007-7-10
 * @author 刘永伟
 * @version 1.0
 */
public class JGroupableTableHeader extends JTableHeader {

  private static final long serialVersionUID = -2066066180933703595L;

  private HeaderComponent headerComponent;

  /**
   * UI绘制类
   */
  private static final String uiClassID = "GroupableTableHeaderUI";

  /**
   * 表头所包含的ColumnGroup
   */
  protected List<ColumnGroup> columnGroups = new Vector<ColumnGroup>();

  public JGroupableTableHeader(TableColumnModel model) {
    super(model);
  }

  /**
   * 添加一个ColumnGroupMode
   * @param group ColumnGroup
   */
  public void addColumnGroup(ColumnGroup group) {
    if (group == null)
      throw new IllegalArgumentException("group 不能为null");
    columnGroups.add(group);
  }

  public ColumnGroup addColumnGroup(Object headerValue, Object[] identifiers) {
    ColumnGroup group = new ColumnGroup(this, headerValue, identifiers);
    addColumnGroup(group);
    return group;
  }

  /**
   * 清除全部的ColumnGroupMode
   */
  public void clearColumnGroups() {
    columnGroups.clear();
  }

  /**
   * 
   * @param column
   * @return column对应的ColumnGroup
   */
  public ColumnGroup getColumnGroupByColumn(TableColumn column) {
    for (ColumnGroup g : getColumnGroups()) {
      if (g.isInclude(column))
        return g;
    }
    return null;
  }

  /**
   * 删除指定的ColumnGroupMode
   * @param group ColumnGroup
   */
  public void removeColumnGroup(ColumnGroup group) {
    if (columnGroups.indexOf(group) > -1) {
      columnGroups.remove(group);
    }
  }

  public int getColumnGroupCount() {
    return columnGroups.size();
  }

  public ColumnGroup[] getColumnGroups() {
    return columnGroups.toArray(new ColumnGroup[columnGroups.size()]);
  }

  @Override
  public void print(Graphics g) {
    super.print(g);
    g.setColor(table.getGridColor());
    g.drawLine(0, headerComponent == null ? 0
      : headerComponent.getPreferredSize().height, 0, getHeight());
    if (headerComponent == null) {
      g.drawLine(0, 0, getWidth(), 0);
    }
  }

  /**
   * 返回col所属于的ColumnGroupMode，如果不被表头包含返回null
   * @return ColumnGroup
   */
  public ColumnGroup getColumnGroup(TableColumn column) {
    for (ColumnGroup cg : columnGroups) {
      if (cg.isInclude(column))
        return cg;
    }
    return null;
  }

  @Override
  public Rectangle getHeaderRect(int column) {
    Rectangle rect = super.getHeaderRect(column);
    if (headerComponent != null && headerComponent.isVisible()) {
      Dimension preferredSize = headerComponent.getPreferredSize();
      rect.height -= preferredSize.height;
      rect.y += preferredSize.height;
    }

    if (getColumnGroup(getColumnModel().getColumn(column)) != null) {
      rect.height /= 2;
      rect.y = rect.height;
      if (getHeaderComponent() != null && getHeaderComponent().isVisible()) {
        rect.y += getHeaderComponent().getPreferredSize().height;
      }
    }
    return rect;
  }

  //  public void updateUI() {
  //    setUI((TableHeaderUI)UIManager.getUI(this));
  //
  //    //setUI(new GroupableTableHeaderUI());
  //    TableCellRenderer renderer = getDefaultRenderer();
  //    if (!(renderer instanceof UIResource) && renderer instanceof Component) {
  //        SwingUtilities.updateComponentTreeUI((Component)renderer);
  //    }
  //  }

  /**
   * Returns the suffix used to construct the name of the look and feel
   * (L&F) class used to render this component.
   * @return the string "TableHeaderUI"
   *
   * @return "TableHeaderUI"
   * @see JComponent#getUIClassID
   * @see UIDefaults#getUI
   */
  @Override
  public String getUIClassID() {
    return uiClassID;
  }

  static {
    UIManager.getDefaults().put(uiClassID, GroupableTableHeaderUI.class.getName());
  }

  public HeaderComponent getHeaderComponent() {
    return headerComponent;
  }

  @Override
  public void paint(Graphics g) {
    super.paint(g);
    if (headerComponent != null && headerComponent.isVisible()) {
      Dimension preferredSize = headerComponent.getPreferredSize();
      g.drawLine(0, preferredSize.height, headerComponent.getWidth(),
        preferredSize.height);
    }
  }

  public void setHeaderComponent(HeaderComponent headerComponent) {
    this.headerComponent = headerComponent;
    this.removeAll();
    this.setLayout(null);
    this.add(headerComponent);
    headerComponent.setBounds(0, 0, getColumnModel().getTotalColumnWidth(),
      headerComponent.getPreferredSize().height);
    this.getTable().addPropertyChangeListener(new PropertyChangeListener() {

      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("model")) {
          SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
              updateHeaderComponentWidth();
            }
          });
        }

      }
    });
    this.getTable().addComponentListener(new ComponentAdapter() {
      @Override
      public void componentResized(ComponentEvent e) {
        super.componentResized(e);
        updateHeaderComponentWidth();
      }
    });
  }

  private synchronized void updateHeaderComponentWidth() {
    if (headerComponent != null && headerComponent.isVisible()) {
      Rectangle rect = new Rectangle(getSize());
      rect.width = Math.min(table.getWidth(), table.getWidth());
      rect.height = JGroupableTableHeader.this.headerComponent.getPreferredSize().height;
      rect.width--;
      JGroupableTableHeader.this.headerComponent.setBounds(rect);
      JGroupableTableHeader.this.headerComponent.revalidate();
      JGroupableTableHeader.this.headerComponent.repaint();
      SwingUtilities
        .updateComponentTreeUI(JGroupableTableHeader.this.headerComponent);

    }
  }

  @Override
  public Dimension getPreferredSize() {
    Dimension size = super.getPreferredSize();
    if (headerComponent != null && headerComponent.isVisible()) {
      size.height += headerComponent.getHeight();
    }
    return size;
  }

  @Override
  public int columnAtPoint(Point point) {
    int allowY = 0;
    if (headerComponent != null && headerComponent.isVisible()) {
      allowY += headerComponent.getHeight();
    }

    int col = super.columnAtPoint(point);

    if (col > -1 && getColumnGroup(getColumnModel().getColumn(col)) != null) {
      allowY += (getBounds().height - (headerComponent == null ? 0 : headerComponent
        .getHeight())) / 2;
    }
    if (point.y <= allowY)
      return -1;
    return col;
  }

  public void fitColumnWidth(int column) {
    fitColumnWidth(column, true);
  }

  /**
   * 自动适配宽度（根据内容长度自动调整）
   * @param column
   */
  void fitColumnWidth(int column, boolean save) {
    String maxString = "";
    JGroupableTable table = getTable();
    synchronized (table) {
      for (int i = 0; i < table.getRowCount(); i++) {
        Object value = table.getDisplayValueAt(i, column);
        if (value != null) {
          String str = value.toString();
          if (str.length() > maxString.length())
            maxString = str;
        }
      }

      TableColumn tableColumn = getColumnModel().getColumn(column);
      Object headValue = tableColumn.getHeaderValue();
      Object dispHeaderValue = headValue;
      if (getTable().getRowSorter() != null)
        dispHeaderValue = dispHeaderValue.toString() + "　　　";
      if (dispHeaderValue.toString().getBytes().length > maxString.getBytes().length) {
        maxString = dispHeaderValue.toString();
      }
      int ctw = getGraphics().getFontMetrics(getFont()).stringWidth(maxString);
      ctw += 10;

      tableColumn.setPreferredWidth(ctw);
      if (save) {
        table.savePreferences();
      }
      //引发列宽改变事件
      getTable().fireColumnResized(new ColumnResizeEvent(getTable(), tableColumn));
    }
  }

  @Override
  public JGroupableTable getTable() {
    return (JGroupableTable) super.getTable();
  }

  @Override
  public GroupableTableHeaderUI getUI() {
    return (GroupableTableHeaderUI) super.getUI();
  }

  @Override
  protected TableCellRenderer createDefaultRenderer() {
    return new DefaultHeaderRenderer();
  }

  @Override
  public void updateUI() {
    setUI(new GroupableTableHeaderUI());
  }

}
